using Moq;
using NUnit.Framework;
using Tycho.Parser.Peg;

namespace Tycho.Parser.Tests.Peg {
    [TestFixture]
    public class GrammarTreeFindInsertionPointSpecification {
        private IProduction RootProduction, AProduction, BProduction, XProduction, YProduction, ZProduction;
        private GrammarTree Root, ATree, BTree, XTree, YTree, ZTree;

        [SetUp]
        public void SetUp () {
            RootProduction = new Mock<IProduction> ().Object;
            Root = new GrammarTree (RootProduction);
            
            AProduction = new Mock<IProduction> ().Object;
            ATree = new GrammarTree (AProduction);
            Root.SubGrammars ["a"] = ATree;

            YProduction = new Mock<IProduction> ().Object;
            YTree = new GrammarTree (YProduction);
            ATree.SubGrammars["y"] = YTree;

            ZProduction = new Mock<IProduction> ().Object;
            ZTree = new GrammarTree (ZProduction);
            YTree.SubGrammars["z"] = ZTree;

            BProduction = new Mock<IProduction> ().Object;
            BTree = new GrammarTree (BProduction);
            Root.SubGrammars ["b"] = BTree;
            XProduction = new Mock<IProduction> ().Object;
            XTree = new GrammarTree (XProduction);
            BTree.SubGrammars ["x"] = XTree;
        }

        [Test]
        public void ShouldFindInsertionPointFromJustOnePathComponent () {
            var insertionPoint = Root.FindInsertionPoint (new [] { "a" });
            Assert.That (insertionPoint.ParentProduction, Is.EqualTo (RootProduction));
            Assert.That (insertionPoint.Production, Is.EqualTo (AProduction));
        }

        [Test]
        public void ShouldFindInsertionPointFromTwoPathComponents () {
            var insertionPoint = Root.FindInsertionPoint (new [] { "b", "x" });
            Assert.That (insertionPoint.ParentProduction, Is.EqualTo (BProduction));
            Assert.That (insertionPoint.Production, Is.EqualTo (XProduction));
        }

        [Test]
        public void ShouldFindInsertionPointFromThreePathComponents () {
            var insertionPoint = Root.FindInsertionPoint (new [] { "a", "y", "z" });
            Assert.That (insertionPoint.ParentProduction, Is.EqualTo (YProduction));
            Assert.That (insertionPoint.Production, Is.EqualTo (ZProduction));
        }
    }
}